<template>
  <div class="log-detail">
    <div class="custom-header">
      <span class="back-area" @click="onBack">
        <svg class="back-icon" viewBox="0 0 16 16" width="18" height="18">
          <path d="M10.5 13 6 8l4.5-5" stroke="#bfbfbf" stroke-width="1.5" fill="none" stroke-linecap="round"
            stroke-linejoin="round" />
        </svg>
        <span class="back-text">返回</span>
      </span>
      <span class="header-divider">|</span>
      <span class="header-title">日志</span>
    </div>

    <div class="content-outer">
      <div class="content-card">
        <div class="toolbar">
          <span class="toolbar-title">采集日志</span>
          <a-space>
            <a-button type="primary" :loading="downloading" @click="onExport">
              <DownloadOutlined /> 日志下载
            </a-button>
          </a-space>
        </div>

        <a-divider style="margin: 12px 0" />

        <!-- 筛选条 -->
        <div class="filter-bar">
          <div class="filter-input-group">
            <a-input v-model:value="search_text" placeholder="输入搜索" class="filter-input" allow-clear
              @pressEnter="onSearch" />
            <a-button class="filter-btn" @click="onSearch">搜索</a-button>
          </div>

          <span class="filter-label">日志类型：</span>
          <a-select v-model:value="log_level" class="filter-select" @change="onSearch"
            :getPopupContainer="getPopupContainer">
            <a-select-option value="全部">全部</a-select-option>
            <a-select-option value="INFO">INFO</a-select-option>
            <a-select-option value="WARN">WARN</a-select-option>
            <a-select-option value="ERROR">ERROR</a-select-option>
            <a-select-option value="DEBUG">DEBUG</a-select-option>
          </a-select>

          <span class="filter-label">时间范围：</span>
          <a-select v-model:value="timeQuick" class="filter-select" placeholder="选择范围" @change="onQuickChange"
            :getPopupContainer="getPopupContainer">
            <a-select-option value="">选择范围</a-select-option>
            <a-select-option value="10m">最近10分钟</a-select-option>
            <a-select-option value="1h">最近1小时</a-select-option>
            <a-select-option value="today">今天</a-select-option>
            <a-select-option value="yesterday">昨天</a-select-option>
            <a-select-option value="7d">近7天</a-select-option>
          </a-select>

          <!-- 带时分秒的日期范围，展示更宽 -->
          <a-range-picker v-model:value="range" class="range-picker" show-time format="YYYY-MM-DD HH:mm:ss"
            valueFormat="YYYY-MM-DD HH:mm:ss" :getPopupContainer="getPopupContainer" :allowClear="true"
            :placeholder="['开始日期', '结束日期']" @change="onRangeChange" />
        </div>

        <a-spin :spinning="loading">
          <div class="log-body">
            <pre class="log-pre">{{ renderText }}</pre>
          </div>
        </a-spin>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { DownloadOutlined } from '@ant-design/icons-vue'
import { message } from 'ant-design-vue'
import Http from '@/api'

const router = useRouter()
const route = useRoute()

/** 让下拉/日历挂在触发节点父元素或 body，避免被日志区域遮挡 */
const getPopupContainer = (node?: HTMLElement) => {
  if (node && node.parentElement) return node.parentElement
  // @ts-ignore
  return typeof window !== 'undefined' && typeof document !== 'undefined' ? document.body : undefined
}

const indexId = ref<string>('')

const loading = ref(false)
const downloading = ref(false)

const logText = ref<string>('')
const renderText = ref<string>('')

/** 筛选字段（与后端一致） */
const search_text = ref<string>('')
const log_level = ref<string>('全部')
const timeQuick = ref<string>('')
const range = ref<[string, string] | null>(null)

/* 时间（到日） */
function pad(n: number) { return String(n).padStart(2, '0') }
function dateStr(d: Date) { return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}` }
function dayStartStr(d: Date) { return `${dateStr(d)} 00:00:00` }
function dayEndStr(d: Date) { return `${dateStr(d)} 23:59:59` }

function getRangeByQuick(key: string): { start_time: string; end_time: string } {
  if (!key) return { start_time: '', end_time: '' }
  const now = new Date()
  switch (key) {
    case '10m': { const s = new Date(now.getTime() - 10 * 60 * 1000); return { start_time: dayStartStr(s), end_time: dayEndStr(now) } }
    case '1h': { const s = new Date(now.getTime() - 60 * 60 * 1000); return { start_time: dayStartStr(s), end_time: dayEndStr(now) } }
    case 'today': return { start_time: dayStartStr(now), end_time: dayEndStr(now) }
    case 'yesterday': {
      const y = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1)
      return { start_time: dayStartStr(y), end_time: dayEndStr(y) }
    }
    case '7d': {
      const s = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 6)
      return { start_time: dayStartStr(s), end_time: dayEndStr(now) }
    }
    default: return { start_time: '', end_time: '' }
  }
}

function buildQueryPayload() {
  let start_time = ''
  let end_time = ''
  if (range.value && range.value.length === 2) {
    start_time = range.value[0]
    end_time = range.value[1]
  } else {
    const r = getRangeByQuick(timeQuick.value || '')
    start_time = r.start_time
    end_time = r.end_time
  }
  return {
    index_id: Number(indexId.value) || 0,
    log_level: (log_level.value || '').toUpperCase() === '全部'.toUpperCase() ? '' : (log_level.value || ''),
    search_text: (search_text.value || '').trim(),
    start_time,
    end_time,
  }
}

async function fetchLog() {
  const id = (indexId.value || '').trim()
  if (!id) { logText.value = ''; renderText.value = ''; return }
  loading.value = true
  try {
    const payload = buildQueryPayload()
    const res: any = await (Http as any).createIndexTaskLog(payload)
    const raw = typeof res?.data !== 'undefined' ? res.data : res
    if (typeof raw === 'string') {
      logText.value = raw
    } else if (Array.isArray(raw)) {
      logText.value = raw.map((it: any) => {
        const t = it.time || it.timestamp || it.create_time || ''
        const lvl = it.log_level || it.level || ''
        const msg = it.message || it.text || it.log || it.content || ''
        return `${t ? `[${t}] ` : ''}${lvl ? `[${lvl}] ` : ''}${msg}`
      }).join('\n')
    } else if (raw && typeof raw === 'object') {
      if (Array.isArray(raw.list)) {
        logText.value = raw.list.map((it: any) => {
          const t = it.time || it.timestamp || it.create_time || ''
          const lvl = it.log_level || it.level || ''
          const msg = it.message || it.text || it.log || it.content || ''
          return `${t ? `[${t}] ` : ''}${lvl ? `[${lvl}] ` : ''}${msg}`
        }).join('\n')
      } else {
        logText.value = raw.content ?? raw.text ?? raw.log ?? raw.message ?? ''
      }
    } else {
      logText.value = ''
    }
    renderText.value = logText.value
  } catch (e: any) {
    logText.value = ''
    renderText.value = ''
    message.error(`获取日志失败：${e?.message || '网络错误'}`)
  } finally {
    loading.value = false
  }
}

function onSearch() { fetchLog() }
function onQuickChange() { range.value = null; onSearch() }
function onRangeChange(val: [string, string] | null) { if (val && val.length === 2) timeQuick.value = ''; onSearch() }

watch(log_level, () => onSearch())
watch(search_text, v => { if ((v || '').trim() === '') onSearch() })

function onExport() {
  downloading.value = true
  try {
    const now = new Date()
    const ts = `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}-${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`
    const name = `collect-log_${indexId.value || 'index'}_${ts}.txt`
    const blob = new Blob([renderText.value || ''], { type: 'text/plain;charset=utf-8' })
    const url = URL.createObjectURL(blob)
    const a = document.createElement('a')
    a.href = url
    a.download = name
    a.click()
    URL.revokeObjectURL(url)
  } finally {
    downloading.value = false
  }
}

function onBack() { router.go(-1) }

watch(
  () => route.query.index_id,
  (val) => {
    indexId.value = Array.isArray(val) ? String(val?.[0] ?? '') : String(val ?? '')
    fetchLog()
  },
  { immediate: true }
)
</script>

<style lang="less" scoped>
@primary: #1677ff;
@border-light: #f0f0f0;
@bg-page: #f5f6f8;
@text-secondary: #595959;

.log-detail {
  position: absolute;
  inset: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  background: @bg-page;
  box-sizing: border-box;

  .custom-header {
    flex: 0 0 56px;
    height: 56px;
    background: #fff;
    border-bottom: 1px solid @border-light;
    display: flex;
    align-items: center;
    padding: 0 16px;
  }

  .back-area {
    display: inline-flex;
    align-items: center;
    cursor: pointer;
    user-select: none;
    font-size: 16px;
    color: #8c8c8c;
    transition: color .2s;
    padding-right: 4px;

    &:hover .back-text,
    &:hover .back-icon {
      color: @primary;
      stroke: @primary;
    }
  }

  .back-icon {
    margin-right: 2px;
    color: #bfbfbf;
    stroke: #bfbfbf;
    margin-left: 14px;
  }

  .back-text {
    font-size: 14px;
    color: @text-secondary;
    margin-right: 8px;
    line-height: 100%;
  }

  .header-divider {
    width: 1px;
    height: 16px;
    background: #d9d9d9;
    display: inline-block;
    margin: 0 8px;
    font-size: 0;
  }

  .header-title {
    font-size: 16px;
    font-weight: 500;
    color: #262626;
    letter-spacing: 0;
    line-height: 100%;
    margin-left: 8px;
  }

  .content-outer {
    flex: 1;
    display: flex;
    margin: 10px;
    min-height: 0;
  }

  .content-card {
    position: relative;
    width: 100%;
    background: #fff;
    border-radius: 8px;
    padding: 16px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .06);
    display: flex;
    flex-direction: column;
    min-height: 0;
  }

  .toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;

    .toolbar-title {
      font-size: 14px;
      font-weight: 600;
      color: #333;
    }
  }

  .filter-bar {
    position: relative;
    z-index: 30;
    background: #fff;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 12px;
    margin: 12px 0 14px;

    .filter-input-group {
      display: inline-flex;
      align-items: stretch;
      height: 32px;
    }

    /* —— 只修改搜索框（开始） —— */
    .filter-input {
      width: 340px;
      /* 加宽，内容完整展示 */
    }

    /* 让外层 affix-wrapper 占满 .filter-input 宽度，并与按钮连体 */
    .filter-input-group :deep(.ant-input-affix-wrapper) {
      width: 100%;
      display: inline-flex;
      align-items: center;
      height: 32px;
      box-sizing: border-box;
      border-top-right-radius: 0 !important;
      border-bottom-right-radius: 0 !important;
      border-right: none !important;
      position: relative;
      z-index: 1;
      /* 默认在按钮之上，避免被盖住描边 */
    }

    /* 聚焦时再抬高，蓝色描边不会被按钮挡住 */
    .filter-input-group :deep(.ant-input-affix-wrapper-focused) {
      z-index: 2;
    }

    /* 内部真实 input 的高度与行高，防止上下被裁切 */
    .filter-input-group :deep(.ant-input-affix-wrapper .ant-input) {
      height: 30px;
      line-height: 30px;
    }

    .filter-btn {
      min-width: 72px;
      height: 32px;
      border-top-left-radius: 0 !important;
      border-bottom-left-radius: 0 !important;
      margin-left: -1px;
      /* 与输入框边框无缝衔接 */
      position: relative;
      z-index: 0;
    }

    /* —— 只修改搜索框（结束） —— */

    .filter-label {
      color: #333;
      font-size: 14px;
      margin: 0 4px 0 8px;
      white-space: nowrap;
    }

    .filter-select {
      width: 220px;
    }

    .range-picker {
      width: 480px;
      height: 32px;
    }
  }

  :deep(.ant-spin-nested-loading) {
    flex: 1;
    min-height: 0;
    display: flex;
  }

  :deep(.ant-spin-container) {
    flex: 1;
    min-height: 0;
    display: flex;
  }

  .log-body {
    flex: 1;
    min-height: 0;
    margin-top: 16px;
    z-index: 1;
    overflow: auto;
    background: #0b0f16;
    color: #b7c0d4;
    border-radius: 8px;
    padding: 12px;
    line-height: 1.6;

    &::-webkit-scrollbar {
      width: 8px;
      height: 8px;
    }

    &::-webkit-scrollbar-thumb {
      background: #2a3140;
      border-radius: 8px;
    }

    &::-webkit-scrollbar-track {
      background: transparent;
    }

    scrollbar-width: thin;
    scrollbar-color: #2a3140 transparent;
  }

  .log-pre {
    margin: 0;
    white-space: pre-wrap;
    word-break: break-all;
    font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;
  }

  @media (max-width: 576px) {
    .filter-bar {
      gap: 8px;

      .filter-input {
        width: 100%;
      }

      .filter-select,
      .range-picker {
        width: 100%;
      }
    }
  }
}
</style>
